package com.qingcloud.adminbackend.service.impl;

import cn.hutool.db.ds.simple.SimpleDataSource;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qingcloud.adminbackend.base.AjaxResult;
import com.qingcloud.adminbackend.constant.WamingConstant;
import com.qingcloud.adminbackend.entity.source.DataSource;
import com.qingcloud.adminbackend.entity.source.DataSourceDatabase;
import com.qingcloud.adminbackend.entity.source.DataSourceDatabaseDto;
import com.qingcloud.adminbackend.enums.DataSourceTypeEnum;
import com.qingcloud.adminbackend.enums.DatabaseTypeEnum;
import com.qingcloud.adminbackend.mapper.DataSourceMapper;
import com.qingcloud.adminbackend.mapper.DatabaseMapper;
import com.qingcloud.adminbackend.mapper.DatasourceDatabaseMapper;
import com.qingcloud.adminbackend.service.IDatasourceDatabaseService;
import com.qingcloud.adminbackend.utils.CookieUtil;
import com.qingcloud.adminbackend.utils.DbUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Connection;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wangjinnan
 * @since 2021-03-17
 */
@Service
public class DatasourceDatabaseServiceImpl extends ServiceImpl<DatasourceDatabaseMapper, DataSourceDatabaseDto> implements IDatasourceDatabaseService {

    @Resource
    private DatasourceDatabaseMapper datasourceDatabaseMapper;

    @Resource
    private DataSourceMapper dataSourceMapper;

    @Resource
    private DatabaseMapper databaseMapper;

    @Override
    public AjaxResult add(DataSourceDatabaseDto dataSourceDatabase) {
        if (dataSourceDatabase == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "对象不能为空", "");
        if (dataSourceDatabase.getProjectId() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "projectId参数不能为空", "");
        if (dataSourceDatabase.getDsType() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "dsType参数不能为空", "");
        if (dataSourceDatabase.getDsName() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "dsName参数不能为空", "");
        if (dataSourceDatabase.getIp() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "ip参数不能为空", "");
        if (dataSourceDatabase.getDbType() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "dbType参数不能为空", "");
        if (dataSourceDatabase.getPort() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "port参数不能为空", "");
        if (dataSourceDatabase.getUsername() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "username参数不能为空", "");
        if (dataSourceDatabase.getPassword() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "password参数不能为空", "");
        if (dataSourceDatabase.getCatalog() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "catalog参数不能为空", "");
        DataSource datasource = new DataSource();
        datasource.setName(dataSourceDatabase.getDsName());
        datasource.setProjectId(dataSourceDatabase.getProjectId());
        datasource.setType(dataSourceDatabase.getDsType());
        dataSourceMapper.addDatasource(datasource);
        if (datasource.getId() == null) return new AjaxResult<>(WamingConstant.FAILURE, "写入数据库失败", "");
        DataSourceDatabase database = new DataSourceDatabase();
        database.setIp(dataSourceDatabase.getIp());
        database.setDbType(dataSourceDatabase.getDbType());
        database.setPort(dataSourceDatabase.getPort());
        database.setDsId(datasource.getId());
        database.setUsername(dataSourceDatabase.getUsername());
        database.setPassword(dataSourceDatabase.getPassword());
        database.setCatalog(dataSourceDatabase.getCatalog());
        String jdbcUrl = DbUtil.getJdbcUrl(database.getIp(), database.getPort(),
                DatabaseTypeEnum.getByCode(database.getDbType()), database.getCatalog());
        database.setJdbcUrl(jdbcUrl);
        int addFlag = databaseMapper.addDatabase(database);
        if (addFlag <= 0) {
            dataSourceMapper.deleteDatasourceByIds(Collections.singletonList(datasource.getId() + ""));
            return new AjaxResult<>(WamingConstant.FAILURE, "新增失败", "");
        } else return new AjaxResult<>(WamingConstant.SUCCESS, "新增成功", "");
    }

    /**
     * 测试数据源
     */
    @Override
    public AjaxResult test(Integer dsId) {
        //获取数据源信息
        DataSourceDatabase database = databaseMapper.getDatabaseByDataSourceId(dsId);
        //获取连接
        boolean isConnect = false;
        try (SimpleDataSource simpleDataSource = new SimpleDataSource(database.getJdbcUrl(), database.getUsername(), database.getPassword())) {
            Connection connection = simpleDataSource.getConnection();
            connection.close();
            isConnect = true;
        } catch (Exception e) {
            //ignore
        }
        if (isConnect) {
            return new AjaxResult<>(WamingConstant.SUCCESS, "连接成功", "");
        }
        return new AjaxResult<>(WamingConstant.FAILURE, "连接失败", "");
    }

    @Override
    public AjaxResult updateDataSourceDatabase(DataSourceDatabaseDto dataSourceDatabase) {
        if (dataSourceDatabase == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "对象不能为空", "");
        if (dataSourceDatabase.getDsId() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "dsId参数不能为空", "");
        if (dataSourceDatabase.getDbId() == null)
            return new AjaxResult<>(WamingConstant.FAILURE, "dbId参数不能为空", "");
        List<DataSource> dataSourceList = dataSourceMapper.findDatasourceByIds(
                new ArrayList<>(Collections.singletonList(dataSourceDatabase.getDsId() + "")));
        if (dataSourceList.size() == 0) return new AjaxResult<>(WamingConstant.FAILURE, "无该数据源", "");
        DataSource dataSource = new DataSource();
        dataSource.setId(dataSourceDatabase.getDsId());
        dataSource.setName(dataSourceDatabase.getDsName());
        dataSource.setType(dataSourceDatabase.getDsType());
        dataSource.setProjectId(dataSourceDatabase.getProjectId());
        String check = DataSource.check(dataSource);
        if (!check.equalsIgnoreCase("true"))
            return new AjaxResult<>(WamingConstant.FAILURE, check, "");

        List<DataSourceDatabase> databaseList = databaseMapper.findDatabaseByIds(new ArrayList<>(Collections.singletonList(dataSourceDatabase.getDbId() + "")));
        if (databaseList.size() == 0) return new AjaxResult<>(WamingConstant.FAILURE, "无该数据库", "");
        DataSourceDatabase database = new DataSourceDatabase();
        database.setId(dataSourceDatabase.getDbId());
        database.setIp(dataSourceDatabase.getIp());
        database.setPort(dataSourceDatabase.getPort());
        database.setCatalog(dataSourceDatabase.getCatalog());
        database.setUsername(dataSourceDatabase.getUsername());
        database.setPassword(dataSourceDatabase.getPassword());
        database.setDsId(dataSourceDatabase.getDsId());
        database.setDbType(dataSourceDatabase.getDbType());
        String jdbcUrl = DbUtil.getJdbcUrl(database.getIp(), database.getPort(),
                DatabaseTypeEnum.getByCode(database.getDbType()), database.getCatalog());
        database.setJdbcUrl(jdbcUrl);
        check = DataSourceDatabase.check(database);
        if (!check.equalsIgnoreCase("true"))
            return new AjaxResult<>(WamingConstant.FAILURE, check, "");

        int addFlag = dataSourceMapper.updateDatasource(dataSource);
        if (addFlag <= 0) return new AjaxResult<>(WamingConstant.FAILURE, "修改失败", "");
        else {
            addFlag = databaseMapper.updateDatabase(database);
            if (addFlag <= 0) return new AjaxResult<>(WamingConstant.FAILURE, "修改失败", "");
            else return new AjaxResult<>(WamingConstant.SUCCESS, "修改成功", "");
        }
    }

    @Override
    public AjaxResult deleteByDsIds(String dsIds) {
        if (dsIds == null) return new AjaxResult<>(WamingConstant.FAILURE, "ids参数不能为空", null);
        String[] idArr = dsIds.split(",");
        if (idArr.length == 0) return new AjaxResult<>(WamingConstant.FAILURE, "ids参数不能为空", null);
        List<String> dsIdList = Arrays.asList(idArr);
        List<DataSourceDatabaseDto> dataSourceDatabaseDtos = datasourceDatabaseMapper.findByDsIds(dsIdList);
        List<String> dbIdList = dataSourceDatabaseDtos.stream()
                .map(it -> String.valueOf(it.getDbId())).collect(Collectors.toList());
        int addFlag = dataSourceMapper.deleteDatasourceByIds(dsIdList);
        if (addFlag <= 0) return new AjaxResult<>(WamingConstant.FAILURE, "删除失败", "");
        else {
            addFlag = databaseMapper.deleteDatabaseByIds(dbIdList);
            if (addFlag <= 0) return new AjaxResult<>(WamingConstant.FAILURE, "删除失败", "");
            else return new AjaxResult<>(WamingConstant.SUCCESS, "删除成功", "");
        }
    }

    @Override
    public AjaxResult copyByDsId(String dsId) {
        if (dsId == null) return new AjaxResult<>(WamingConstant.FAILURE, "dsId参数不能为空", null);
        List<DataSourceDatabaseDto> dataSourceDatabaseDtos = datasourceDatabaseMapper.findByDsIds(Collections.singletonList(dsId));
        if (dataSourceDatabaseDtos == null) return new AjaxResult<>(WamingConstant.FAILURE, "无目标数据源", null);
        DataSourceDatabaseDto dataSourceDatabaseDto = dataSourceDatabaseDtos.get(0);
        List<DataSource> dataSources = dataSourceMapper.findDatasourceByIds(Collections.singletonList(dataSourceDatabaseDto.getDsId() + ""));
        if (dataSources == null) return new AjaxResult<>(WamingConstant.FAILURE, "无目标数据源", null);
        List<DataSourceDatabase> databases = databaseMapper.findDatabaseByIds(Collections.singletonList(dataSourceDatabaseDto.getDbId() + ""));
        if (databases == null) return new AjaxResult<>(WamingConstant.FAILURE, "无目标数据库", null);
        DataSource dataSource = dataSources.get(0);
        dataSource.setName(dataSource.getName() + "-复制");
        dataSourceMapper.addDatasource(dataSource);
        if (dataSource.getId() == null) new AjaxResult<>(WamingConstant.FAILURE, "写入失败", null);
        DataSourceDatabase database = databases.get(0);
        database.setCatalog(database.getCatalog() + "-复制");
        database.setDsId(dataSource.getId());
        databaseMapper.addDatabase(database);
        return new AjaxResult<>(WamingConstant.SUCCESS, "复制成功", "");
    }

    @Override
    public AjaxResult<List<DataSourceDatabaseDto>> findByDsIds(String dsIds) {
        if (dsIds == null) return new AjaxResult<>(WamingConstant.FAILURE, "ids参数不能为空", null);
        String[] idArr = dsIds.split(",");
        if (idArr.length == 0) return new AjaxResult<>(WamingConstant.FAILURE, "ids参数不能为空", null);
        return new AjaxResult<>(WamingConstant.SUCCESS, "", setTypeName(datasourceDatabaseMapper.findByDsIds(Arrays.asList(idArr))));
    }

    @Override
    public AjaxResult<List<DataSourceDatabaseDto>> findByNameOrProjectId(String dsName, Collection<String> pidSet) {
        return AjaxResult.ok(setTypeName(datasourceDatabaseMapper.findByNameOrProjectId(dsName, pidSet)));
    }

    private List<DataSourceDatabaseDto> setTypeName(List<DataSourceDatabaseDto> dataSourceDatabaseDtoList) {
        dataSourceDatabaseDtoList.forEach(it -> {
            it.setDsTypeName(DataSourceTypeEnum.getTitleByCode(it.getDsType()));
            it.setDbTypeName(DatabaseTypeEnum.getByCode(it.getDbType()).title);
        });
        return dataSourceDatabaseDtoList;
    }
}
